﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
using CrmContrib.Workflow.Activities.SSRSExecution;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Workflow;

namespace CrmContrib.Workflow.Activities.Invoicing
{
    /// <summary>
    /// Workflow activity for executing an external report hosted with SSRS
    /// </summary>
    /// <remarks>
    /// By convention the report linked to this activity should have a parameter called CRM_FilteredInvoice that accepts a query to drive the invoice report.
    /// </remarks>
    [CrmWorkflowActivity("Generate a Pdf (external)", "CrmContrib \\ Invoicing")]
    public class GenerateInvoiceAsPdf_FromExternalReportActivity : Activity
    {
        //TODO: document parameter usage
        [CrmInput("Invoice")]
        [CrmReferenceTarget("invoice")]
        [ValidationOption(ValidationOption.Required)]
        public Lookup Invoice
        {
            get { return (Lookup)base.GetValue(InvoiceProperty); }
            set { base.SetValue(InvoiceProperty, value); }
        }

        public static readonly DependencyProperty InvoiceProperty = DependencyProperty.Register("Invoice", typeof(Lookup), typeof(GenerateInvoiceAsPdf_FromExternalReportActivity));

        [CrmInput("Report Path")]
        [ValidationOption(ValidationOption.Required)]
        public string ReportPath
        {
            get { return (string)base.GetValue(ReportPathProperty); }
            set { base.SetValue(ReportPathProperty, value); }
        }

        public static readonly DependencyProperty ReportPathProperty = DependencyProperty.Register("ReportPath", typeof(string), typeof(GenerateInvoiceAsPdf_FromExternalReportActivity));

        [CrmInput("Report Server URL")]
        [ValidationOption(ValidationOption.Required)]
        public string ReportServerUrl
        {
            get { return (string)base.GetValue(ReportServerUrlProperty); }
            set { base.SetValue(ReportServerUrlProperty, value); }
        }

        public static readonly DependencyProperty ReportServerUrlProperty = DependencyProperty.Register("ReportServerUrl", typeof(string), typeof(GenerateInvoiceAsPdf_FromExternalReportActivity));

        private void SetExecutionParameters(ReportExecutionService reportService, ExecutionInfo reportInfo)
        {
            string criteria = string.Format("select invoice0.* from invoice invoice0 where ( invoice0.invoiceid = '{0}' )", Invoice.Value);

            var parameters = new List<ReportParameter>(reportInfo.Parameters);
            var invoiceFilters = parameters.Where(x => (x.Name == "P1") || (x.Name == "CRM_FilteredInvoice")).Select(x => new ParameterValue { Name = x.Name, Value = criteria });

            reportService.SetExecutionParameters(invoiceFilters.ToArray(), "en-US");
        }

        /// <summary>
        /// Renders the report and saves the output into the FileRegistry.
        /// </summary>
        /// <param name="reportPath"></param>
        /// <returns></returns>
        private Guid RenderReport(string reportPath)
        {
            byte[] output;

            using (var rs = new ReportExecutionService())
            {
                string extension;
                string mimetype;
                string encoding;
                Warning[] warnings;
                string[] streamIds;
                string reportFormat = "PDF";
                string deviceInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";

                rs.UseDefaultCredentials = true;
                rs.Url = ReportServerUrl;

                rs.ExecutionHeaderValue = new ExecutionHeader();
                ExecutionInfo executionInfo = rs.LoadReport(reportPath, null);  //there could be connection issues here if default connection string in report does not exist
                SetExecutionParameters(rs, executionInfo);

                output = rs.Render(reportFormat, deviceInfo, out extension, out mimetype, out encoding, out warnings, out streamIds);
            }

            return FileRegistry.AddFile(output).FileID;
        }

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            FileID = RenderReport(ReportPath).ToString();

            return base.Execute(executionContext);
        }

        [CrmOutput("File ID")]
        public string FileID
        {
            get { return (string)base.GetValue(FileIDProperty); }
            set { base.SetValue(FileIDProperty, value); }
        }

        public static readonly DependencyProperty FileIDProperty = DependencyProperty.Register("FileID", typeof(string), typeof(GenerateInvoiceAsPdf_FromExternalReportActivity));

    }
}
